package de.freudenreichdesign.webshop.service;

import java.util.List;
import java.util.Set;
import java.util.Date;

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import de.freudenreichdesign.webshop.model.Adress;
import de.freudenreichdesign.webshop.model.Customer;
import de.freudenreichdesign.webshop.model.Person;
import de.freudenreichdesign.webshop.model.User;
import de.freudenreichdesign.webshop.persistence.DatabaseUtil;

@Service("accountService")
public class AccountService implements UserDetailsService {

	private static AccountService accountService = null;
	private DatabaseUtil databaseUtil = null;
	
	private AccountService() {
		databaseUtil = DatabaseUtil.getInstance();
	}
	
	public synchronized static AccountService getInstance() {
		if (accountService == null)
			accountService = new AccountService();
		return accountService;
	}
	
	public Customer getCustomerByID(long customerID) {
		return (Customer)databaseUtil.getObject(Customer.class.getName(), customerID);
	}
	
	public Person getPersonByID(long personID) {
		return (Person)databaseUtil.getObject(Person.class.getName(), personID);
	}
	
	public Adress getAdressByID(long adressID) {
		return (Adress)databaseUtil.getObject(Adress.class.getName(), adressID);
	}
	
	public void createCustomer(String title, String gender, String firstName,
			String lastName, String eMail, String phoneNumber, Date dateOfBirth,
			String country, String city, String state, int zipCode,
			String street, int number, String additionalInfo) {
		while (databaseUtil.startSaveTransaction() == false);
		Adress adress = new Adress(country, city, state, zipCode, street, number, additionalInfo);
		Person person = new Person(title, gender, firstName, lastName, adress, eMail, phoneNumber);
		Customer customer = new Customer(person, dateOfBirth, new Date());
		databaseUtil.bufferBeforeSaveCommit(customer);
		databaseUtil.saveCommit();
	}
	
	public void changeCustomerData(long customerID, String title, String gender, String firstName,
			String lastName, String eMail, String phoneNumber, Date dateOfBirth) {
		Customer customer = getCustomerByID(customerID);
		while (databaseUtil.startSaveTransaction() == false);
		customer.setDateOfBirth(dateOfBirth);
		customer.getPerson().seteMail(eMail);
		customer.getPerson().setFirstName(firstName);
		customer.getPerson().setLastName(lastName);
		customer.getPerson().setGender(gender);
		customer.getPerson().setPhoneNumber(phoneNumber);
		customer.getPerson().setTitle(title);
		databaseUtil.bufferBeforeSaveCommit(customer);
		databaseUtil.saveCommit();
	}
	
	public void deleteCustomer(long customerID, Date inactiveDate) {
		Customer customer = getCustomerByID(customerID);
		while (databaseUtil.startSaveTransaction() == false);
		customer.setInactiveSince(inactiveDate);
		databaseUtil.bufferBeforeSaveCommit(customer);
		databaseUtil.saveCommit();
	}
	
	public void createAndAddAdress(long personID, String country, String city, String state, int zipCode,
			String street, int number, String additionalInfo) {
		Person person = getPersonByID(personID);
		while (databaseUtil.startSaveTransaction() == false);
		Adress adress = new Adress(country, city, state, zipCode, street, number, additionalInfo);
		addAdressToList(person.getListOfAdresses(), adress);
		databaseUtil.bufferBeforeSaveCommit(person);
		databaseUtil.saveCommit();
	}
	
	public void changeAdress(long personID, long adressID, String country, String city, String state, int zipCode,
			String street, int number, String additionalInfo) {
		Adress adress = getAdressFromListByID(getPersonByID(personID).getListOfAdresses(), adressID);
		while (databaseUtil.startSaveTransaction() == false);
		adress.setAdditionalInfo(additionalInfo);
		adress.setCity(city);
		adress.setCountry(country);
		adress.setNumber(number);
		adress.setState(state);
		adress.setStreet(street);
		adress.setZipCode(zipCode);
		databaseUtil.bufferBeforeSaveCommit(adress);
		databaseUtil.saveCommit();
	}
	
	public void deleteAdress(long personID, long adressID) {
		Person person = getPersonByID(personID);
		Set<Adress> listOfAdresses = person.getListOfAdresses();
		Adress adress = getAdressFromListByID(person.getListOfAdresses(), adressID);
		if (adress != null) databaseUtil.remove(adress);
		while (databaseUtil.startSaveTransaction());
		if (!listOfAdresses.isEmpty()){
			int position = -1;
			for (int i = 0; i < listOfAdresses.size(); i++) {
				if (((Adress) listOfAdresses.toArray()[i]).getAdressID() == adressID) 
					position = i;
			}
			listOfAdresses.remove(position);
		}
		databaseUtil.bufferBeforeSaveCommit(person);
		databaseUtil.saveCommit();
	}
	
	public List<Object> getOrderListFromCustomer(long customerID) {
		return databaseUtil.executeQuery("from Order as order where order.customer.id="  + customerID);
	}
	
	private Adress getAdressFromListByID(Set<Adress> listOfAdresses, long adressID) {
		for (Adress adress : listOfAdresses) {
			if (adress.getAdressID() == adressID)
				return adress;
		}
		return null;
	}
	
	private void addAdressToList(Set<Adress> listOfAdresses, Adress adress) {
		listOfAdresses.add(adress);
	}

	@Override
	public UserDetails loadUserByUsername(String userName)
			throws UsernameNotFoundException, DataAccessException {
		return (User) databaseUtil.executeQuery("from User as user where user.username = "  + userName);
	}
}
